import axios from "axios"
import { useAuthStore } from "@/stores/auth"; //用户信息保存的位置
class Http{
    constructor(){ //构造函数
        this.instance = axios.create({  //创建了一个 axios 实例，并存储在类的实例属性 instance
            //baseURL:'http://127.0.0.1:8000',  //写死的情况基本url，设置万后跳转只需要后面内容/auth/login 
            baseURL: import.meta.env.VITE_BASE_URL, //通过读取之前定义的环境变量获得
            timeout:5000, //请求超时时间
        });
        
        //为axios的实例定义一个函数，在每次发送请求前被调用
        //interceptors.request 一个属性，每次请求前被调用
        //use表示注册一个新拦截器
        this.instance.interceptors.request.use((config)=>{  //config表示发送请求的所有信息
            
            //console.log(config); //{transitional: {…}, adapter: Array(3), transformRequest: Array(1), transformResponse: Array(1), timeout: 5000, …}
            const authstore = useAuthStore() //将定义的存储实例化
            const token = authstore.token  //获取token属性
            if(token){  //添加到config字段中
                config.headers.Authorization = 'JWT ' + token //JWT后一定要加空格，这才符合JWT格式要求
            }
            return config
        })

    }

    post(path,data){ //类方法，用于发送POST请求
        //path: /auth/login 会自动拼接成http://127.0.0.1:8000/auth/login
        //return this.instance.post(path,data)
        return new Promise(async (resolve,reject)=>{  //回一个新的 Promise 对象。
            //async 关键字允许在函数内部使用 await  resolve：当异步操作成功完成时调用  reject：当异步操作失败时调用
            //Promise 对象 :JavaScript 是单线程的,为了不阻塞主线程，某些操作被设计为异步的，即在后台执行，完成后再通知主线程
            //一个 Promise 对象代表了一个可能还没有完成，但最终会完成的操作
            //this.instance.post(path,data) //使用 await 关键字等待 axios 发送的 POST 请求完成
            //await ：网络请求发送后，线程会挂起，等数据回复后，线程才会回到往前位置继续执行
            //只能在async中使用
            //axios底层也是用的Promise对象，相应状态码不是200时就会调用reject，此时的外层函数（await）会报异常
            try{
                let result = await this.instance.post(path,data) //await等待axios发送的网络请求
                resolve(result.data); //Promise 被解决，并返回响应的数据部分
            }catch(err){ //此时状态码肯定不是200
                try{
                    let detail = err.response.data.detail;
                    reject(detail)  //Promise 被拒绝，并返回错误的详细信息
                }catch{
                    reject('服务器错误！')
                }           
            }            
        })
    }

    get(path, params){  //发送get请求
        return new Promise(async (resolve, reject) => {  //Promise是JavaScript中用于异步编程
            try{
                let result = await this.instance.get(path, {params}) //await等待axios发送的get网络请求
                resolve(result.data)
            }catch(err){
                let detail = err.response.data.detail; //从错误响应中提取错误详情
                reject(detail)
            }
        })
    }

    put(path,data){
        return new Promise(async (resolve,reject)=>{ 
            try{
                let result = await this.instance.put(path,data) //await等待axios发送的网络请求
                resolve(result.data); //Promise 被解决，并返回响应的数据部分
            }catch(err){ //此时状态码肯定不是200
                console.log(err);
                let detail = err.response.data.detail;
                reject(detail)  //Promise 被拒绝，并返回错误的详细信息
            }
        })
    }

    delete(path){
        return new Promise(async (resolve,reject)=>{ 
            try{
                let result = await this.instance.delete(path) //await等待axios发送的网络请求
                resolve(result); //服务端的delete方法只返回状态码，并没有数据，所以直接返回result
            }catch(err){ //此时状态码肯定不是200
                console.log(err);
                let detail = err.response.data.detail;
                reject(detail)  //Promise 被拒绝，并返回错误的详细信息
            }
        })
    }

    downloadFile(path,params){
        return new Promise(async (resolve, reject) => {  //Promise是JavaScript中用于异步编程
            try{
                let result = await this.instance.get(path, {
                    params, //发送给服务器的参数
                    responseType:'blob' //定响应类型为blob，这意味着期望从服务器接收二进制数据，这对于下载文件
                }) //await等待axios发送的get网络请求
                resolve(result.data)
            }catch(err){
                let detail = err.response.data.detail; //从错误响应中提取错误详情
                reject(detail)
            }
        })
    }
}

export default new Http() //导出了一个 Http 类的实例,其他文件可使用